﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="UriHelper.cs" company="Collaboris Ltd.">
//   Copyright (c) Collaboris Ltd. All rights Reserved.
// </copyright>
// <summary>
//   Defines the UriHelper type.
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace Collaboris.Utils
{
    using System;
    using System.Diagnostics;
    using System.IO;

    /// <summary>
    /// </summary>
    public static class UriHelper
    {
        /// <summary>
        /// Returns the AbsolutePath for a given absolute Uri
        /// </summary>
        /// <param name="AbsoluteUri"></param>
        /// <example>'http://localhost/site1/site2/list2' returns '/site1/site2/list2'</example>
        /// <returns></returns>
        public static string GetAbsolutePath(string AbsoluteUri)
        {
            // Trace.If(traceSwitch.TraceVerbose, TraceLevel.Verbose, "Starting Utils.GetAbsolutePath");

            try
            {
                if (AbsoluteUri == string.Empty)
                {
                    return string.Empty;
                }

                Uri uri = new Uri(AbsoluteUri);

                // Trace.If(traceSwitch.TraceVerbose, TraceLevel.Verbose, "Ending Utils.GetAbsolutePath");
                return uri.AbsolutePath;
            }
            catch (Exception ex)
            {
                Trace.TraceError("Error found in Utils.GetAbsolutePath. Error ToString() : '{0}'", ex.ToString());
                return string.Empty;
            }
        }

        /// <summary>
        /// Gets the server relative URL from full URL.
        /// </summary>
        /// <param name="url">The STR URL.</param>
        /// <returns></returns>
        public static string GetServerRelUrlFromFullUrl(string url)
        {
            int index = url.IndexOf("//");
            if ((index < 0) || (index == (url.Length - 2)))
            {
                throw new ArgumentException();
            }

            int startIndex = url.IndexOf('/', index + 2);
            if (startIndex < 0)
            {
                return "/";
            }

            string str = url.Substring(startIndex);
            if (str.IndexOf("?") >= 0)
                str = str.Substring(0, str.IndexOf("?"));

            if (str.IndexOf(".aspx") > 0)
                str = str.Substring(0, str.LastIndexOf("/"));

            if ((str.Length > 1) && (str[str.Length - 1] == '/'))
            {
                return str.Substring(0, str.Length - 1);
            }
            return str;
        }

        /// <summary>
        /// Splits a Url
        /// </summary>
        /// <remarks>
        /// /* * "countOccurences" can be found in Snippet 490  *  
        ///  * * @params url (like "http://www.mydomain.com/mypath/somefile.html")  
        ///  * * @returns str[0] ("somefile.html")  
        ///  * * @returns str[1] ("http://www.mydomain.com/mypath/")  
        ///  */
        /// </remarks>
        /// <param name="url">string url to search for</param>
        /// <returns>string array containing path and page name</returns>
        public static string[] SplitUrl(string url)
        {
            if (!url.ToLower().Contains("http://"))
            {
                return SplitRelativeUrl(url);
            }

            //this.Trace.TraceMethodStart("SPWebHelper.SplitURL");
            string[] fullUrl = new string[2];
            if (url.LastIndexOf("/") == url.Length || CountOccurrences(url, "/") <= 2)
            {
                if (CountOccurrences(url, "/") == 1)
                {
                    fullUrl[0] = "/";
                    fullUrl[1] = url.Substring(1);
                }
                else
                {
                    fullUrl[0] = null;
                    fullUrl[1] = url;
                }
            }
            else
            {
                fullUrl[1] = url.Substring(url.LastIndexOf("/") + 1);
                fullUrl[0] = url.Substring(0, url.LastIndexOf("/"));
            }

            //this.Trace.TraceMethodEnd("SPWebHelper.SplitURL");
            return fullUrl;
        }

        /// <summary>
        /// Splits a Relative Url into 
        /// path and page/object name.
        /// </summary>
        /// <param name="url"></param>
        /// <remarks>
        /// /* * "countOccurences" can be found in Snippet 490  *  
        ///  * * @params url (like "/mypath/somefile.html")  
        ///  * * @returns str[0] ("somefile.html")  
        ///  * * @returns str[1] ("/mypath/")  
        ///  */
        /// </remarks>
        /// <returns>string array containing path and page name</returns>
        public static string[] SplitRelativeUrl(string url)
        {
            if (url.ToLower().Contains("://"))
            {
                return SplitUrl(url);
            }
            //this.Trace.TraceMethodStart("SPWebHelper.SplitRelativeURL");
            string[] fullUrl = new string[2];
            if (url.LastIndexOf("/") == url.Length || CountOccurrences(url, "/") <= 1)
            {
                if (CountOccurrences(url, "/") == 1)
                {
                    fullUrl[0] = "/";
                    fullUrl[1] = url.Substring(1);
                }
                else
                {
                    fullUrl[0] = null;
                    fullUrl[1] = url;
                }

            }
            else
            {
                fullUrl[1] = url.Substring(url.LastIndexOf("/") + 1);
                fullUrl[0] = url.Substring(0, url.LastIndexOf("/"));
            }
            return fullUrl;
            //this.Trace.TraceMethodEnd("SPWebHelper.SplitRelativeURL");
        }

        /// <summary>
        /// Counts the number of Occurrences of a particular 
        /// string (needle), with in a larger string (haystack).
        /// </summary>
        /// <param name="haystack">String to search within</param>
        /// <param name="needle">string pattern to count</param>
        /// <returns>int number of occurrences</returns>
        public static int CountOccurrences(String haystack, String needle)
        {
            //this.Trace.TraceMethodStart("SPWebHelper.CountOccurrences");
            int count = 0;
            int index = 0;
            while ((index = haystack.IndexOf(needle, index)) != -1)
            {
                ++index;
                ++count;
            }
            //this.Trace.TraceMethodEnd("SPWebHelper.CountOccurrences");
            return count;
        }

        /// <summary>
        /// Gets the virtual path portion of the given absolute URL 
        /// relative to the given base path.
        /// </summary>
        /// <remarks>
        /// Base path comparison is done case insensitive.
        /// </remarks>
        /// <param name="basePath">the absolute base path</param>
        /// <param name="url">the absolute url</param>
        /// <returns>the url relative to the given basePath</returns>
        public static string GetRelativePath(string basePath, string url)
        {
            // strip application path from url
            string appPath = basePath.TrimEnd('/');
            string appRelativeVirtualPath = url;
            if (appRelativeVirtualPath.ToLower().StartsWith(appPath.ToLower()))
            {
                appRelativeVirtualPath = appRelativeVirtualPath.Substring(appPath.Length);
            }
            return appRelativeVirtualPath;
        }

        /// <summary>
        /// Combines the specified base address.
        /// </summary>
        /// <param name="baseAddress">The base address.</param>
        /// <param name="relativeAddress">The relative address.</param>
        /// <returns></returns>
        public static string Combine(string baseAddress, string relativeAddress)
        {
            Uri baseUri = new Uri(baseAddress);
            return new Uri(baseUri, relativeAddress).ToString();
        }
    }
}
